#ifndef JSON_H_
#define JSON_H_

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#define JSON_LEXER_STACK_MAX 20
#define JSON_PARSER_NEST_MAX 5


typedef enum {
  OFFLINE,
  ONLINE,
  SEND
} RUNNER_A0_STATE_t;


// List of symbols
typedef enum {
  empty = 0,
  lbrace, // {
  rbrace, // }
  colon,  // :
  comma,  // ,
  lbrak,  // [
  rbrak,  // ]
  string,
  integer,
  real,
  null
} Symbols_t;

// Lexer symbol
typedef struct {
  Symbols_t sym;    // Symbol lbrace, real...
  char *id;         // Symbol identificator start position
  int len;          // Symbol identificator length
} Symbol;

// JSON field types
typedef enum {
  TYPE_JSON = -1,
  TYPE_INTEGER = integer,
  TYPE_REAL = real,
  TYPE_STRING = string
} JSON_TYPE_t;

typedef struct json_node_s{
  char*   name;          // Object name
  void*   value;         // Points to the string, int, double, char or an array depends of "type" field
  int     count;         // Data count. If count>1 JSON node is an array of "type"
  int     type;          // Data type (JSON, INTEGER, REAL, STRING)
  struct json_node_s *next, *prev, *child, *parent;   
} json_node;


json_node*  json_node_create();
void        json_node_destroy(json_node* node);
json_node*  json_node_find(char* name, json_node* node);

// Parse string and return pointer to json_node if JSON is valid
bool json_parse_string(char* str, json_node** node);

// Parse input character and returns pointer to json_node if JSON is valid
bool json_parse_char(char c, json_node** node);

// Reset JSON automaton before using json_parse char
void json_parse_init();

#ifdef JSON_PRIVATE_
  // Syntax analyzer routines, implemented in parser.c and lexer.c
  
  // Parse character from input string
  // Returns 1 - if character accepted, 0 - if character not accepted
  bool json_get_symbol(char c, Symbol* out);  

  // Parse JSON string "in place". Memory allocation only for json_node tree.
  // Returns root of JSON tree, or NULL if input string contains invalid JSON.
  bool json_parse_symbol(Symbol* s);

  void json_error(char message[]);
  void json_set_value(Symbol* symbol);
  void json_add_value(Symbol* symbol);

  void json_lexer_reset();

  // Memory management routines, implemented in node.cpp
  void json_node_add_next(json_node* node);
  void json_node_add_child(json_node* node);
  void json_node_set_name(json_node* node, char* name, int len);
//  void json_node_set_value(json_node* node, void* value, int type, int len);
//  void json_node_add_value(json_node* node, void* value, int type, int len);
#endif

#endif /* JSON_H_ */